package com.mes.task.dao;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.MatchMode;
import org.hibernate.criterion.Property;
import org.hibernate.criterion.Restrictions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import com.bstek.dorado.data.provider.Page;
import com.mes.basicdata.dao.EmployeeDao;
import com.mes.common.dao.BasicDao;
import com.mes.common.util.SysUtil;
import com.mes.task.dao.iface.IPartTaskDao;
import com.mes.task.domain.DemandTaskLink;
import com.mes.task.domain.OperationTask;
import com.mes.task.domain.PartTask;

@Repository
public class PartTaskDao extends BasicDao<PartTask> implements IPartTaskDao {

	private final static Log log = LogFactory.getLog(PartTaskDao.class);

	@Autowired
	SysUtil sysUtil;
	@Autowired
	EmployeeDao employeeDao;


	/**
	 * @author lcs
	 * 通过任务好、图号、批次、状态获得AO装配任务
	 * @param partTaskId
	 * @param drawingId
	 * @param batchNum
	 * @param taskState
	 * @param page
	 * @return
	 */
	@Override
	public List<PartTask> getAOTasksByPartTaskId(String taskId,
			String drawingId, String batchNum, Integer taskState, Page page) {

		List<PartTask> list = null;
		try {
			DetachedCriteria crit = DetachedCriteria.forClass(PartTask.class);
			crit.createAlias("part", "part");
			crit.add(Restrictions.eq("taskId", taskId));
			crit.add(Restrictions.eq("taskType", PartTask.TASKTYPE_VIRTUAL_AO));
			if (drawingId != null && !"".equals(drawingId)) {
				crit.add(Restrictions.like("part.drawingId", drawingId,
						MatchMode.ANYWHERE));
			}
			if (batchNum != null && !"".equals(batchNum)) {
				crit.add(Restrictions.like("batchNum", batchNum,
						MatchMode.ANYWHERE));
			}
			if (taskState != null && !"".equals(taskState)) {
				crit.add(Restrictions.eq("taskState", taskState));
			}
			crit.addOrder(Property.forName("taskUid").asc());
			
			if (page != null) {
				this.pagingQuery(page, crit);
			} else {
				list = this.query(crit, null);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}

		return list;
	}
	
	
	/**
	 * 根据partTaskUid获得工序任务信息列表，并安装operationId排序
	 * 
	 * @param taskUid
	 * @return
	 */
	public List<OperationTask> getOperationTasks(String partTaskUid) {
		Session session = this.getSessionFactory().getCurrentSession();
		List list = null;
		try {
			StringBuffer hql = new StringBuffer("from " + OperationTask.class.getName() + " where ");
			hql.append("parentUid = ? ");
			hql.append("order by operationId ");
			Query query = session.createQuery(hql.toString());
			query.setString(0, partTaskUid);
			list = query.list();
			return list;
		} finally {
			session.flush();
		}
	}

	/**
	 * 根据partTaskUid获得工序任务信息列表，并安装operationId排序
	 * 
	 * @param taskUid
	 * @return
	 */
	public List<OperationTask> getOperationTasks(String partTaskUid, double operationId) {
		Session session = this.getSessionFactory().getCurrentSession();
		List list = null;
		try {
			StringBuffer hql = new StringBuffer("from " + OperationTask.class.getName() + " where ");
			hql.append("parentUid = ? and operationId > ?");
			hql.append("order by operationId ");
			Query query = session.createQuery(hql.toString());
			query.setString(0, partTaskUid);
			query.setDouble(1, operationId);
			list = query.list();
			return list;
		} finally {
			session.flush();
		}
	}

	/**
	 * 通过partUid获取在制任务
	 * 
	 * @param partUid
	 * @return
	 */
	@Override
	public List<PartTask> getWipPartTasksByPartUid(String partUid) {
		List list = null;
		try {
			Session session = this.getSessionFactory().getCurrentSession();
			StringBuilder hql = new StringBuilder();
			hql.append("from " + PartTask.class.getName() + " where ");
			hql.append(" taskState < 106 ");
			hql.append("  and partUid=? order by batchNum");
			Query query = session.createQuery(hql.toString());
			query.setString(0, partUid);

			list = query.list();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return list;
	}

	/**
	 * 返回demand（计划、指令）的关联零件任务
	 * 
	 * @param demandUid
	 * @param page
	 * @return
	 */
	public List<PartTask> getPartTasksByDemandUid(String demandUid, Page<PartTask> page) {
		List<PartTask> list2 = null;
		List<DemandTaskLink> list = null;
		try {
			Session session = this.getSessionFactory().getCurrentSession();
			Criteria crit = session.createCriteria(DemandTaskLink.class);
			crit.add(Restrictions.eq("demandUid", demandUid)).add(Restrictions.eq("dependType", "1"));
			crit.add(Restrictions.eq("isInEffect", DemandTaskLink.ISINEFFECT_IS));
			list = crit.list();
			List<String> partTaskUid = new ArrayList<String>(list.size());
			for (Object li : list) {
				DemandTaskLink dtl = (DemandTaskLink) li;
				partTaskUid.add(dtl.getPartTaskUid());
			}

			if (partTaskUid != null && partTaskUid.size() > 0) {
				DetachedCriteria crit2 = DetachedCriteria.forClass(PartTask.class);
				crit2.add(Restrictions.in("taskUid", partTaskUid));
				crit2.addOrder(Property.forName("createTime").desc());
				// 如果需要进行分页处理，则调用如下语句
				if (page != null) {
					this.pagingQuery(page, crit2);
				} else {
					list2 = this.query(crit2, null);
				}
			} else {
				return null;
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return list2;
	}

	/**
	 * 通过物料唯一号和批次号返回零件任务
	 * 
	 * @param partUid
	 * @param batchNum
	 * @return
	 */
	@Override
	public PartTask getPartTaskByPartUidAndBatchNum(String partUid, String batchNum) {
		PartTask partTask = null;
		try {
			Session session = this.getSessionFactory().getCurrentSession();
			Criteria crit = session.createCriteria(PartTask.class);
			crit.add(Restrictions.eq("partUid", partUid));
			crit.add(Restrictions.eq("batchNum", batchNum));
			partTask = (PartTask) crit.uniqueResult();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		return partTask;
	}

	/**
	 * 通过主制部门和物料唯一号获取在制零件任务(已投产并且未完成)
	 * 
	 * @param masterShopUid
	 * @param partUid
	 * @return
	 */
	@Override
	public List<PartTask> getWipPartTasksByDeptAndPart(String masterShopUid, String partUid) {
		List<PartTask> list = null;
		try {
			Session session = this.getSession();
			Criteria crit = session.createCriteria(PartTask.class);
			crit.add(Restrictions.eq("partUid", partUid));
			crit.add(Restrictions.like("masterShopUid", masterShopUid + "%"));
			// by zy 2016-06-19 投产的任务看不到
			crit.add(Restrictions.gt("taskState", PartTask.TASKSTATE_PLANED));
			crit.add(Restrictions.lt("taskState", PartTask.TASKSTATE_COMPLETED));
			crit.add(Restrictions.gt("planQty", 0d));
			crit.add(Restrictions.or(Restrictions.isNull("isSuspended"),
					Restrictions.eq("isSuspended", PartTask.SUSPENDED_NO)));
			list = crit.list();
		} catch (Exception e) {
			e.printStackTrace();
		}

		return list;
	}

	/**
	 * 通过主制部门获取在制零件任务(已投产并且未完成)
	 * 
	 * @param masterShopUid
	 * @return
	 */
	@Override
	public List<PartTask> getWipPartTasksByDept(String masterShopUid) {
		List<PartTask> list = null;
		try {
			Session session = this.getSession();
			Criteria crit = session.createCriteria(PartTask.class);
			crit.add(Restrictions.like("masterShopUid", masterShopUid + "%"));
			crit.add(Restrictions.gt("taskState", PartTask.TASKSTATE_PLANED));
			crit.add(Restrictions.lt("taskState", PartTask.TASKSTATE_COMPLETED));
			crit.add(Restrictions.gt("planQty", 0f));
			crit.add(Restrictions.or(Restrictions.isNull("isSuspended"),
					Restrictions.eq("isSuspended", PartTask.SUSPENDED_NO)));

			list = crit.list();
		} catch (Exception e) {
			e.printStackTrace();
		}

		return list;
	}

	/**
	 * 通过原来的批次号，得到新的分批后的零件任务
	 * 
	 * @param partNumber
	 * @param batchnum
	 * @return List<PartTask>
	 */
	@Override
	public List<PartTask> getAllBatchedPartTasks(String partNumber, String batchnum) {
		Session session = this.getSession();
		Criteria crit = session.createCriteria(PartTask.class);
		crit.add(Restrictions.eq("partUid", partNumber));
		crit.add(Restrictions.eq("rootBatchNum", batchnum));
		crit.add(Restrictions.lt("taskState", PartTask.TASKSTATE_COMPLETED));
		List<PartTask> all = crit.list();
		return all != null ? all : null;
	}

	/**
	 * 获取未分解的零件任务
	 * 
	 * @param page
	 * @return
	 */
	@Override
	public List<PartTask> getUnBreakPartTasks(Page<PartTask> page) {
		List<PartTask> list = null;
		try {
			DetachedCriteria crit = DetachedCriteria.forClass(PartTask.class);
			crit.add(Restrictions.lt("taskState", PartTask.TASKSTATE_DISASSEMBLE));
			crit.add(Restrictions.or(Restrictions.isNull("isSuspended"),
					Restrictions.eq("isSuspended", PartTask.SUSPENDED_NO)));
			crit.addOrder(Property.forName("partDrawingId").asc()).addOrder(Property.forName("batchNum").asc());
			if (page != null) {
				this.pagingQuery(page, crit);
			} else {
				list = this.query(crit, null);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}

		return list;
	}

	/**
	 * 获取未分解的零件任务
	 * 
	 * @param partUid
	 * @param page
	 * @return
	 */
	@Override
	public List<PartTask> getUnBreakPartTasksByPartUid(String partUid, Page<PartTask> page) {
		List<PartTask> list = null;
		try {
			DetachedCriteria crit = DetachedCriteria.forClass(PartTask.class);
			crit.createAlias("part", "p");
			crit.add(Restrictions.eq("partUid", partUid));
			crit.add(Restrictions.like("masterShopUid", sysUtil.getSessionDeptUid().substring(0, 4) + "%"));
			crit.add(Restrictions.lt("taskState", PartTask.TASKSTATE_DISASSEMBLE));
			crit.add(Restrictions.or(Restrictions.isNull("isSuspended"),
					Restrictions.eq("isSuspended", PartTask.SUSPENDED_NO)));
			crit.addOrder(Property.forName("p.drawingId").asc()).addOrder(Property.forName("batchNum").asc());
			if (page != null) {
				this.pagingQuery(page, crit);
			} else {
				list = this.query(crit, null);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}

		return list;
	}

	/**
	 * 获取未分解的零件任务
	 * 
	 * @param drawingId
	 * @param page
	 * @return
	 */
	@Override
	public List<PartTask> getUnBreakPartTasks(String drawingId, Page<PartTask> page) {
		List<PartTask> list = null;
		try {
			DetachedCriteria crit = DetachedCriteria.forClass(PartTask.class);
			crit.createAlias("part", "p");
			if (drawingId != null && !("".equals(drawingId))) {
				crit.add(Restrictions.ilike("p.drawingId", drawingId, MatchMode.START));
			}

			crit.add(Restrictions.like("masterShopUid", sysUtil.getSessionDeptUid().substring(0, 4) + "%"));
			crit.add(Restrictions.lt("taskState", PartTask.TASKSTATE_DISASSEMBLE));
			crit.add(Restrictions.or(Restrictions.isNull("isSuspended"),
					Restrictions.eq("isSuspended", PartTask.SUSPENDED_NO)));
			crit.addOrder(Property.forName("p.drawingId").asc()).addOrder(Property.forName("createTime").desc());
			if (page != null) {
				this.pagingQuery(page, crit);
			} else {
				list = this.query(crit, null);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}

		return list;
	}

	/**
	 * 查找某段时间厂外协作加工回来的零件任务
	 * 
	 * @param fromDate
	 * @param toDate
	 * @return
	 */
	@Override
	public List<PartTask> getWaixiePartTasksByReturnTime(Date fromDate, Date toDate) {
		List<PartTask> list = new ArrayList();
		try {
			List<String> lstTaskUid = null;
			Session session = this.getSession();
			String sql = "select distinct t.parentuid as taskuid from t_tasks t "
					+ "inner join t_assignments a on a.taskuid=t.taskuid and a.assntype=1"
					+ "inner join r_resource r on r.resuid=a.resuid " + "where a.resuid like 'wxcj%' "
					+ "and exists(select 1 from i_ioheader h inner join i_iodetail d on h.invioid=d.invioid "
					+ "where h.iotype=106  and d.relationid=t.taskuid and h.iodate between ? and ?) ";
			Query query = session.createSQLQuery(sql);
			query.setTimestamp(0, fromDate);
			query.setTimestamp(1, toDate);

			lstTaskUid = query.list();
			for (int i = 0; i < lstTaskUid.size(); i++) {
				PartTask parttask = this.getById(lstTaskUid.get(i));
				list.add(parttask);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}

		return list;
	}

	/**
	 * 通过parentTaskUid获得零件任务
	 * 
	 * @param parentTaskUid
	 * @param page
	 * @return
	 */
	@Override
	public List<PartTask> getPartTasksByParentUid(String parentTaskUid, Page<PartTask> page) {

		List<PartTask> list = null;
		try {
			DetachedCriteria crit = DetachedCriteria.forClass(PartTask.class);
			crit.add(Restrictions.eq("parentTaskUid", parentTaskUid));
			crit.addOrder(Property.forName("taskType").desc()).addOrder(Property.forName("taskUid").asc());
			if (page != null) {
				this.pagingQuery(page, crit);
			} else {
				list = this.query(crit, null);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}

		return list;
	}

	@Override
	public List<PartTask> getAOTasksByContignationNumber(String contignationNumber) {
		List<PartTask> list = null;
		try {
			Session session = this.getSession();
			Criteria crit = session.createCriteria(PartTask.class);
			crit.add(Restrictions.eq("contignationNumber", contignationNumber));
			crit.add(Restrictions.eq("taskType", PartTask.TASKTYPE_VIRTUAL_AO));
			crit.addOrder(Property.forName("taskUid").asc());
			list = crit.list();
		} catch (Exception e) {
			e.printStackTrace();
		}

		return list;
	}

	@Override
	public List<PartTask> getAOTasksByRoutingUid(String routingUid, String contignationNumber) {

		List<PartTask> list = null;
		try {
			Session session = this.getSession();
			Criteria crit = session.createCriteria(PartTask.class);
			crit.add(Restrictions.eq("routingUid", routingUid));
			crit.add(Restrictions.eq("contignationNumber", contignationNumber));
			crit.add(Restrictions.eq("taskType", PartTask.TASKTYPE_VIRTUAL_AO));
			crit.addOrder(Property.forName("taskUid").asc());
			list = crit.list();
		} catch (Exception e) {
			e.printStackTrace();
		}

		return list;
	}

	@Override
	public List<PartTask> getAOTasksByParentTaskUid(String parentTaskUid, Page<PartTask> page) {

		List<PartTask> list = null;
		try {
			DetachedCriteria crit = DetachedCriteria.forClass(PartTask.class);
			crit.add(Restrictions.eq("parentTaskUid", parentTaskUid));
			crit.add(Restrictions.eq("taskType", PartTask.TASKTYPE_VIRTUAL_AO));
			crit.addOrder(Property.forName("taskUid").asc());
			if (page != null) {
				this.pagingQuery(page, crit);
			} else {
				list = this.query(crit, null);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}

		return list;
	}

	// @Override
	// public List<PartTask> getAOTasksByParentTaskUid(String parentTaskUid) {
	//
	// List<PartTask> list = null;
	// try {
	// Session session = this.getSession();
	// Criteria crit = session.createCriteria(PartTask.class);
	// crit.add(Restrictions.eq("parentTaskUid", parentTaskUid));
	// crit.add(Restrictions.like("taskType", "1", MatchMode.START));
	// crit.addOrder(Property.forName("taskType").desc()).addOrder(Property.forName("taskUid").asc());
	// list = crit.list();
	// } catch (Exception e) {
	// e.printStackTrace();
	// }
	//
	// return list;
	// }

	@Override
	public List<PartTask> getAOTasksByPartTaskId(String partTaskId, Page<PartTask> page) {
		List<PartTask> list = null;
		try {
			DetachedCriteria crit = DetachedCriteria.forClass(PartTask.class);
			crit.add(Restrictions.eq("partTaskId", partTaskId));
			crit.add(Restrictions.eq("taskType", PartTask.TASKTYPE_VIRTUAL_AO));
			crit.addOrder(Property.forName("taskUid").asc());
			if (page != null) {
				this.pagingQuery(page, crit);
			} else {
				list = this.query(crit, null);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}

		return list;
	}

	@Override
	public PartTask getProductTaskByPartTaskId(String partTaskId) {

		PartTask partTask = null;
		try {
			Session session = this.getSession();
			Criteria crit = session.createCriteria(PartTask.class);
			crit.add(Restrictions.eq("partTaskId", partTaskId));
			crit.add(Restrictions.eq("taskType", PartTask.TASKTYPE_VIRTUAL_DEMAND));
			partTask = (PartTask) crit.uniqueResult();
		} catch (Exception e) {
			e.printStackTrace();
		}

		return partTask;
	}

	/**
	 * 通过这三个属性获取唯一的零组件任务
	 * 
	 * @param partUid
	 * @param batchNum
	 * @param masterShopUid
	 * @return
	 */
	@Override
	public PartTask getPartTaskByPartUidAndBatchNum(String partUid, String batchNum, String masterShopUid) {
		PartTask partTask = null;
		try {
			Session session = this.getSession();
			Criteria crit = session.createCriteria(PartTask.class);
			crit.add(Restrictions.eq("partUid", partUid));
			crit.add(Restrictions.eq("batchNum", batchNum));
			crit.add(Restrictions.like("masterShopUid", masterShopUid));
			partTask = (PartTask) crit.uniqueResult();
		} catch (Exception e) {
			e.printStackTrace();
		}

		return partTask;
	}

	/**
	 * 获取某一部门的在制零件任务 from,size两个参数用于分页，如果有一项为空，则不进行分页
	 * 
	 * @param masterShopUid
	 * @param from
	 * @param size
	 * @return
	 */
	@Override
	public List<PartTask> getWipPartTasks(String masterShopUid, Integer from, Integer size) {
		List list = null;
		try {
			Session session = this.getSession();
			StringBuilder hql = new StringBuilder();
			hql.append("from " + PartTask.class.getName() + " where ");
			hql.append(" taskState < 106 ");
			hql.append(" and masterShopUid like ? || '%' ");
			Query query = session.createQuery(hql.toString());
			query.setString(0, masterShopUid);
			if (from != null && size != null && from >= 0 && size >= 0) {
				query.setFirstResult(from);
				query.setMaxResults(size);
			}
			list = query.list();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return list;
	}
	
	@Override
	public void getPartTaskByCondition(Page<PartTask> page, Map<String, Object> params) throws Exception {
		Map<String, Object> args = new HashMap<String, Object>();
		StringBuffer coreHql = new StringBuffer("from PartTask a where 1=1 ");

		if (params != null){
			//批次
			String batchNum = (String) params.get("batchNum");
			if (StringUtils.isNotEmpty(batchNum)) {
				coreHql.append(" and a.batchNum like :batchNum ");
				args.put("batchNum", "%" + batchNum + "%");
			}
			
			//图号
			String partDrawingId = (String) params.get("partDrawingId");
			if (StringUtils.isNotEmpty(partDrawingId)) {
				coreHql.append(" and a.partDrawingId like :partDrawingId ");
				args.put("partDrawingId", "%" + partDrawingId + "%");
			}
			
			//名称
			String taskName = (String) params.get("taskName");
			if (StringUtils.isNotEmpty(taskName)) {
				coreHql.append(" and a.taskName like :taskName ");
				args.put("taskName", "%" + taskName + "%");
			}
			
		}
		
		String countHql = "select count(*) " + coreHql.toString();
		String hql = coreHql.toString();
		
		Map<String, Object> newArgs = new HashMap<String, Object>();
		String key;
		String newKey;
		Iterator<String> iterator = args.keySet().iterator();
		while(iterator.hasNext()){
			key = (String)iterator.next();
			newKey = key.replace(".", "_");
			newArgs.put(newKey, args.get(key));
			hql = hql.replace(":"+key, ":"+newKey);
			countHql = countHql.replace(":"+key, ":"+newKey);
		}
		this.pagingQuery(page, hql, countHql, newArgs);
		
	}

}
